package com.tencent.search.service;

import com.alibaba.fastjson.JSON;
import com.tencent.search.mapper.CourseMapper;
import com.tencent.search.pojo.CourseEntity;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.WeightBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

@Service
public class elasticService {

    @Resource
    private CourseMapper em;

    @Resource
    private ElasticsearchTemplate elasticsearchTemplate;

    public List<CourseEntity> searchFromEs(Map<String, Object> params) {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if(!StringUtils.isEmpty(params.get("key").toString())){
            boolQueryBuilder.filter(QueryBuilders.wildcardQuery("title","%"+params.get("key").toString()+"%"));
        }
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        AggregatedPage<CourseEntity> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), CourseEntity.class);
        return page.getContent();
    }

    public CourseEntity getById(Long id) {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.filter(QueryBuilders.termQuery("id",id));
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        List<CourseEntity> list = elasticsearchTemplate.queryForList(nativeSearchQueryBuilder.build(), CourseEntity.class);
        return list.get(0);
    }

    public Map<String,Object> searchCourse(Map<String,Object> paramMap){
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.parseInt(paramMap.get("page").toString())-1,Integer.parseInt(paramMap.get("limit").toString())));

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //根据关键字查询
        if(null != paramMap.get("title") && !"".equals(paramMap.get("title"))){
            String keyword = (String) paramMap.get("title");
            boolQueryBuilder.filter(QueryBuilders.multiMatchQuery(keyword,"title","outline").minimumShouldMatch("80%").field("title",10));
        }

        if(null != paramMap.get("area_id") && !"".equals(paramMap.get("area_id"))){
            String AreaId = (String) paramMap.get("area_id");
            boolQueryBuilder.filter(QueryBuilders.termQuery("area_id",AreaId));
        }

        //高亮展示
        //高亮字段
        nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("title"));
        //高亮前缀后缀
        nativeSearchQueryBuilder.withHighlightBuilder(new HighlightBuilder().preTags("<font style='color:red'>").postTags("</font>"));

        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        AggregatedPage<CourseEntity> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), CourseEntity.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                ArrayList<T> list = new ArrayList<>();
                for (SearchHit hit : searchResponse.getHits()) {
                    CourseEntity courseEntity = JSON.parseObject(hit.getSourceAsString(), CourseEntity.class);
                    Map<String, HighlightField> highlightFieldMap = hit.getHighlightFields();
                    HighlightField highlightField = highlightFieldMap.get("title");
                    if(null != highlightField){
                        for (Text text : highlightField.getFragments()) {
                            courseEntity.setTitle(text.toString());
                        }
                    }
                    list.add((T)courseEntity);
                }
                return new AggregatedPageImpl<T>(list,pageable,searchResponse.getHits().getTotalHits(),searchResponse.getAggregations());
            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                return null;
            }
        });

        HashMap<String, Object> resultMap = new HashMap<>();
        //数据列表
        resultMap.put("row",page.getContent());
        //数据数量
        resultMap.put("total",page.getTotalElements());
        //总页数
        resultMap.put("totalPage",page.getTotalPages());

        return resultMap;
    }


    public void save(CourseEntity course) {
        em.save(course);
    }

    public void saveAll(List<CourseEntity> list){
        em.saveAll(list);
    }

    public void updateById(CourseEntity courseEntity) {
        em.delete(courseEntity);
        em.save(courseEntity);
    }


    public void delete(Long[] ids) {
        for (Long id : ids) {
            em.deleteById(id);
        }
    }

    public static void main(String[] args) {

        CourseEntity courseEntity = new CourseEntity();

    }
}
